//
// Created by hsj on 2024-1-10.
//
//**************************************************
//不要使用Windows子系统的linux编译测试，特殊阉割版存在问题
//**************************************************
// --------------------------------------
// | URG=1, URG指针=3 | 8 | 9 | 0 |  . |  .
// --------------------------------------
//                                 /|\
//                                  |
//                               URG指针3（紧急消息的下一位3，下标从0开始）
// 如上所述，除紧急指针的前面1个字节外（0），数据接收方将通过调用常用输人函数读取剩余部分。
// 换言之，紧急消息的意义在于督促消息处理，而非紧急传输形式受限的消息。
/**
 *  某次输出：
 *  [root@192 opt]# ./oob_recv.out
    oob serve listen on port:5555
    sigaction state: 0
    Urgent message: 4
    123
    Urgent message: 0
    56789
 */
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <fcntl.h>

#ifdef WIN32
//windows minGW64
//inet_pton函数：_WIN32_WINNT
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#include <winsock2.h>
#include <ws2tcpip.h>
//#pragma comment(lib,"ws2_32.lib")
#else
//linux  gcc
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/wait.h>
#include <signal.h>
#endif

#define BUF_SIZE 100
void error_handling( char *message) ;
void urg_handler(int signo);
int acpt_sock;
int recv_sock;
int main(int argc, char *argv[] ){
    struct sockaddr_in recv_adr, serv_adr;
    int str_len, state;
    socklen_t recv_adr_sz;
    char buf[BUF_SIZE];
    char port[]="5555";

    struct sigaction act;
    memset(&act, '\0', sizeof(act));
    act.sa_handler=urg_handler ;//初始化函数句柄
    sigemptyset(&act.sa_mask);
    act.sa_flags=0;

    acpt_sock=socket(PF_INET, SOCK_STREAM, 0);
    memset(&serv_adr, 0, sizeof(serv_adr));
    serv_adr.sin_family=AF_INET;
    serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);
    serv_adr.sin_port=htons (atoi(/*argv[1]*/port));

    if(bind(acpt_sock, (struct sockaddr*)&serv_adr, sizeof(serv_adr))==-1)
        error_handling("bind() error");
    listen(acpt_sock, 128);
    printf("oob serve listen on port:%s\n",port);

    recv_adr_sz=sizeof(recv_adr);
    recv_sock=accept(acpt_sock, (struct sockaddr* )&recv_adr, &recv_adr_sz);
    if(recv_sock==-1)
        error_handling("accept() error");

    fcntl(recv_sock, F_SETOWN, getpid()); /*使用SIGURG信号前，必须设置socket的宿主进程或进程组，设为当前进程*/
    state=sigaction(SIGURG, &act, 0);
//    signal(SIGURG, urg_handler);//SIGURG
    printf("sigaction state: %d \n", state);//若成功则返回0，若出错则返回-1

    while((str_len=recv(recv_sock, buf, sizeof(buf)-1, 0))!= 0)
    {
        if(str_len==-1){
            printf("occurs error closed client,str_len: %d \n", str_len);
            break;
        }
        buf[str_len]=0;
        printf( "%s \n", buf);
    }
    close(recv_sock);
    close(acpt_sock);

    return EXIT_SUCCESS;
}
void urg_handler(int signo){
//    printf( "Urgent trigger\n");
    int str_len;
    char buf[BUF_SIZE];
    str_len=recv(recv_sock, buf, sizeof(buf)-1, MSG_OOB);
    buf[str_len]=0;
    printf( "Urgent message: %s \n", buf);
}

void error_handling( char *message){
    fputs (message, stderr);
    fputc('\n', stderr);
    exit(1);
}

